/*******************************************************************************
 * Copyright (c) 2013, 2014 EclipseSource and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    EclipseSource - initial API and implementation
 ******************************************************************************/
package org.apache.hop.ui.hopgui;

import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.hop.core.database.RunPython;
import org.apache.hop.core.vfs.HopVfs;
import org.apache.hop.ui.core.PropsUi;
import org.apache.hop.ui.core.dialog.BaseDialog;
import org.apache.hop.ui.core.gui.GuiResource;
import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Chatgpt extends Dialog {
  private static final Class<?> PKG =
      org.apache.hop.ui.core.dialog.ShowBrowserDialog.class; // For Translator

  private static final String[] WIDGETS =
      new String[] {"参考当前文件生成内容", "参考当前文件夹下生成内容", "参考系统帮助", "不参考任何文件"};
  private static final String[] GENTMPLATE =
      new String[] {
        "聊天模型",
        "数据流模板",
        "工作流模板",
        "odata模板",
        "sql模板",
        "python模板",
        "Markdown模板",
        "drawio模板",
        "shell脚本模板",
        "html模板",
        "java模板"
      };
  private final String dialogTitle;
  GridData gdQuest;
  GridData gdAn;
  private String user_prompt = "";
  private Text question;
  private Text answer;
  private Combo widgetCombo;
  private Combo genCombo;
  private Shell shell;
  private FileObject fileObj;
  private boolean isFile = false;

  public Chatgpt(Shell parent, String dialogTitle) {
    super(parent, SWT.NONE);
    this.dialogTitle = dialogTitle;
  }

  /**
   * 设置文件
   *
   * @param fileObj 文件对象
   */
  public void setFileObj(FileObject fileObj) {
    this.fileObj = fileObj;
    try {
      isFile = fileObj.isFile();
      if (!isFile) return;
      String filePath = fileObj.getPath().toString();
      this.user_prompt = new String(Files.readAllBytes(Paths.get(filePath)));
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public void open() {
    Shell parent = getParent();

    shell = new Shell(parent, SWT.MAX | SWT.RESIZE);
    shell.setImage(GuiResource.getInstance().getImageHopUi());
    PropsUi.setLook(shell);
    shell.setText(dialogTitle);
    createStyleControls(shell);
    BaseDialog.defaultShellHandling(shell, c -> ok(), c -> ok());
  }

  public void dispose() {
    shell.dispose();
  }

  private void ok() {
    dispose();
  }

  /** 处理生成按钮的事件 */
  private void handleSetBtn() {
    try {
      answer.setText("大模型思考中......");
      String dir = fileObj.getPath().toString();
      System.out.println("dir=" + dir);
      String ret = "";
      switch (widgetCombo.getSelectionIndex()) {
        case 0: // "参考当前文件生成内容"
          if (isFile) {
            ret = RunPython.runFileChat(dir, question.getText());
          } else {
            MessageBox box = new MessageBox(shell);
            box.setMessage("请选择一个文件");
            box.open();
            ret = "请选择一个文件";
          }
          break;
        case 1: // "参考当前文件夹下的文件生成内容"
          if (isFile) {
            MessageBox box = new MessageBox(shell);
            box.setMessage("请选择一个文件夹");
            box.open();
            ret = "请选择一个文件夹";
          } else {
            ret = RunPython.runDirChat(dir, question.getText());
          }
          break;
        case 2: // , "参考系统默认的帮助知识库"
          ret = RunPython.runDirChat("systemdochelp12345678", question.getText());
          break;
        case 3: // "不参考任何文件"
          ret = RunPython.runFileChat("", question.getText());
          break;
      }
      answer.setText(ret);
    } catch (Exception e) {
      answer.setText("生成失败:" + e);
    }
  }

  protected void createStyleControls(Shell parent) {
    parent.setLayout(new GridLayout(1, false));
    widgetCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
    widgetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    // gridData.horizontalSpan = 2;
    widgetCombo.setItems(WIDGETS);
    if (isFile) widgetCombo.select(0);
    else widgetCombo.select(1);
    genCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
    genCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    genCombo.setItems(GENTMPLATE);
    genCombo.select(0);
    genCombo.addListener(
        SWT.Selection,
        new Listener() {
          @Override
          public void handleEvent(Event event) {
            handleGenCombo();
          }
        });
    SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL | SWT.BORDER);
    GridData shGd = new GridData(GridData.FILL_BOTH);
    sashForm.setLayoutData(shGd);
    question = new Text(sashForm, SWT.MULTI);
    gdQuest = new GridData(GridData.FILL_HORIZONTAL);
    // gdQuest.heightHint = 300;
    question.setLayoutData(gdQuest);
    question.setToolTipText("自定义附加提示词");
    question.setText("你好,");
    // add by bzm:从文件读取base64的prompt提示词
    if (!StringUtils.isEmpty(this.user_prompt)) question.setText(this.user_prompt);
    question.setFont(new Font(question.getDisplay(), "Courier New", 12, SWT.NORMAL));

    answer = new Text(sashForm, SWT.MULTI);
    gdAn = new GridData(GridData.FILL_HORIZONTAL);
    // gdAn.heightHint = 300;
    answer.setLayoutData(gdAn);
    answer.setToolTipText("大模型生成的内容");
    answer.setText("生成内容:");
    answer.setFont(new Font(answer.getDisplay(), "Courier New", 12, SWT.NORMAL));

    Composite comp = new Composite(parent, SWT.NONE);
    comp.setLayout(new GridLayout(3, false));
    comp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
    Button set = new Button(comp, SWT.PUSH);
    set.setText("生成内容");
    set.addListener(
        SWT.Selection,
        new Listener() {
          @Override
          public void handleEvent(Event event) {
            handleSetBtn();
          }
        });
    Button save = new Button(comp, SWT.PUSH);
    save.setText("保存到文件");
    save.addListener(
        SWT.Selection,
        new Listener() {
          @Override
          public void handleEvent(Event event) {
            saveData(answer.getText());
          }
        });
    Button test = new Button(comp, SWT.PUSH);
    test.setText("自动测试");
    test.addListener(
        SWT.Selection,
        new Listener() {
          @Override
          public void handleEvent(Event event) {
            autoTestData(answer.getText());
          }
        });
  }

  /** 处理生成的下拉框类型 */
  private void handleGenCombo() {
    // prompt的提示词需要从数据库读取
    String tmpStr = "";
    switch (genCombo.getSelectionIndex()) {
      case 0: // "自定义"
        tmpStr = "你好,";
        break;
      case 1: // "agent数据流模板"
        tmpStr = "请生成数据流。要求如下：\n" + "1:不要回答任何解释，直接输出xml格式内容。\n" + "2:";
        break;
      case 2: // "agent工作流模板"
        tmpStr = "请生工作流。要求如下：\n" + "1:不要回答任何解释，按xml格式生成内容。\n" + "2:";
        break;
      case 3: // "odata模板"
        tmpStr = "请生成数据流。要求如下：\n" + "1:不要回答任何解释，直接输出xml格式内容。\n" + "2:";
        break;
      case 4: // "sql模板"
        tmpStr = "请生成sql语句,要求如下：\n" + "1:不要回答任何解释。\n" + "2:";
        break;
      case 5: // "python模板", "sql模板","bi模板","js模板","会议总结模板", "自定义"
        tmpStr = "请生成python文件,要求如下：\n" + "1:不要回答任何解释。\n" + "2:";
        break;
      case 6: // "Markdown总结模板", "自定义"
        tmpStr = "要求如下：\n" + "1:不要回答任何解释，按Markdown格式生成内容。\n" + "2:";
        break;
      case 7: // "drawio模板"
        tmpStr = "请生成drawio格式的xml。要求如下：\n" + "1:不要回答任何解释，按xml格式生成内容。\n" + "2:";
        break;
      case 8: // "shell模板","html模板", "sql模板",
        tmpStr = "请生成shell文件。要求如下：\n" + "1:不要回答任何解释。\n" + "2:";
        break;
      case 9: // "html模板"
        tmpStr = "请生成html文件。要求如下：\n" + "1:不要回答任何解释。\n" + "2:";
        break;
      case 10: // "java"
        tmpStr = "请生成java文件。要求如下：\n" + "1:不要回答任何解释，采用java生成内容。\n" + "2:";
        break;
    }
    question.setText(tmpStr);
  }

  /** 根据生成的内容如hpl，wpl，python等，自动测试验证生成 */
  private void autoTestData(String txt) {}

  /** 把生成的内容保存到文件 */
  private void saveData(String txt) {
    // 获取当前日期时间
    LocalDateTime now = LocalDateTime.now();
    // 创建日期时间格式化对象，你可以根据需要调整模式
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
    // 使用格式化对象格式化当前日期时间
    String formattedDateTime = now.format(formatter);
    ExplorerPerspective.TreeItemFolder tif = ExplorerPerspective.getInstance().getSelData();
    if (tif == null) return;
    String dir = tif.path;
    String filename = dir;
    String ext = ".md";
    if (isFile) {
      try {
        dir = fileObj.getParent().getPath().toString();
        filename = dir;
      } catch (FileSystemException e) {
        throw new RuntimeException(e);
      }
    } else {
      switch (genCombo.getSelectionIndex()) {
        case 0: // "自定义"
          ext = ".md";
          break;
        case 1:
          ext = ".hpl";
          break;
        case 2:
          ext = ".hwf";
          break;
        case 3: // "drawio模板"
          ext = ".md";
          break;
        case 4: // "svg模板"
          ext = ".sql";
          break;
        case 5:
          ext = ".py";
          break;
        case 6:
          ext = ".md";
          break;
        case 7:
          ext = ".drawio";
          break;
        case 8:
          ext = ".sh";
          break;
        case 9:
          ext = ".html";
          break;
        case 10: // "sql模板","bi模板","js模板","会议总结模板", "自定义"
          ext = ".java";
          break;
        case 11: // "bi模板","js模板","会议总结模板", "自定义"
          ext = ".bi";
          break;
        case 12: // "js模板","会议总结模板", "自定义"
          ext = ".js";
          break;
        case 13: // "Markdown总结模板", "自定义"
          ext = ".md";
          break;
      }
    }
    MessageBox box = new MessageBox(shell);
    filename += "/" + formattedDateTime + ext;
    try (OutputStream outputStream = HopVfs.getOutputStream(filename, false)) {
      outputStream.write(txt.getBytes(StandardCharsets.UTF_8));
      outputStream.flush();
      box.setMessage("保存成功");
    } catch (Exception e) {
      box.setMessage(e.getMessage());
    }
    box.open();
    ExplorerPerspective.getInstance().refresh();
  }
}
